package com.fausto.learnimprint.core.service.impl

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import com.fausto.learnimprint.cache.RedisCache
import com.fausto.learnimprint.cache.RedisKey
import com.fausto.learnimprint.core.mapper.DiscussMapper
import com.fausto.learnimprint.core.model.entity.Discuss
import com.fausto.learnimprint.core.service.IBlogService
import com.fausto.learnimprint.core.service.IDiscussService
import com.fausto.learnimprint.core.service.IUserService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.crossstore.ChangeSetPersister.NotFoundException
import org.springframework.security.authentication.AuthenticationServiceException
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDateTime

/**
 *
 *
 * 服务实现类
 *
 *
 * @author fausto
 * @since 2022-03-28
 */
@Service
class DiscussServiceImpl :
    ServiceImpl<DiscussMapper, Discuss>(),
    IDiscussService {

    @Autowired
    lateinit var discussMapper: DiscussMapper

    @Autowired
    lateinit var userService: IUserService

    @Autowired
    lateinit var blogService: IBlogService

    /**
     *      获取最新评论六条
     *          + AOP缓存处理
     */
    @RedisCache(key = RedisKey.DISCUSS_KEY)
    override fun latestComments(): List<Discuss> {
        return discussMapper.findLatest(6)
    }

    /**
     *      保存评论
     */
    @Transactional(rollbackFor = [Exception::class])
    override fun saveDiscuss(blogId: Int, discussBody: String) {
        //从HTTP请求中获取用户信息
        val user = userService.findUserFromContext()
        //通过博客ID查询博客
        val blog = blogService.findBlogById(blogId)
        //保存评论
        discussMapper.insert(Discuss().apply {
            this.userId = user.userId
            this.blogId = blog.blogId
            this.discussBody = discussBody
            this.discussTime = LocalDateTime.now()
        })
        //更新博文(局部更新)
        blogService.update(
            null,
            UpdateWrapper<com.fausto.learnimprint.core.model.entity.Blog>()
                .set("blog_discussCount", blog.blogDiscussCount + 1)
                .eq("blog_id", blogId)
        )
    }


    /**
     *      根据评论ID删除评论
     *          只有评论发布者或管理员有权限删除
     */
    @Transactional(rollbackFor = [Exception::class])
    override fun deleteDiscuss(discussId: Int): Boolean {
        //获取用户信息
        val user = userService.findUserFromContext()
        //待删除评论
        val discuss = findDiscussById(discussId)
        //是否是管理员
        val isAdmin = userService.getRoles(user).contains("ADMIN")
        //若该用户不是评论发布者或该用户不具备管理员权限,则无权限执行删除操作
        return if (discuss.userId == user.userId) {
            discussMapper.deleteById(discussId) > 0
        } else if (isAdmin) {
            discussMapper.deleteById(discussId) > 0
        } else {
            throw AuthenticationServiceException("用户无权限执行删除操作")
        }
    }


    /**
     *      通过ID查询评论
     */
    @RedisCache(key = RedisKey.DISCUSS_KEY)
    override fun findDiscussById(discussId: Int): Discuss {
        return discussMapper.selectById(discussId) ?: throw NotFoundException()
    }

    /**
     *      分页查询特定博客下的所有评论
     */
    @RedisCache(key = RedisKey.DISCUSS_KEY)
    override fun findDiscussPage(
        blogId: Int,
        page: Int,
        showCount: Int
    ): List<Discuss> {
        return discussMapper.selectPage(
            Page(page.toLong(), showCount.toLong()),
            QueryWrapper<Discuss>().eq("blog_id", blogId)
        ).records
    }

    /**
     *      获取用户的所有评论
     */
    @RedisCache(key = RedisKey.DISCUSS_KEY)
    override fun findUserDiscuss(): List<Discuss> {
        val user = userService.findUserFromContext()
        return discussMapper.selectList(
            QueryWrapper<Discuss>().eq("user_id", user.userId)
        )
    }
}